#region Using

using System;
using System.Globalization;
using System.Collections.Generic;
using System.ComponentModel;

#endregion

namespace BlogEngine.Core
{
	/// <summary>
	/// Represents a comment to an item.
	/// </summary>
	[Serializable]
	public sealed class Comment : PublishableBase<Comment>, IComparable<Comment>
	{
		/// <summary>
		/// default constructor
		/// </summary>
		public Comment()
			: base()
		{
		}

		#region Properties

		private string _Email = string.Empty;
		/// <summary>
		/// Gets or sets the email.
		/// </summary>
		/// <value>The email.</value>
		public string Email
		{
			get { return _Email; }
			set { _Email = value; }
		}

		private Uri _Website;

		/// <summary>
		/// Gets or sets the website.
		/// </summary>
		/// <value>The website.</value>
		public Uri Website
		{
			get { return _Website; }
			set { _Website = value; }
		}

		private string _Country = string.Empty;
		/// <summary>
		/// Gets or sets the country.
		/// </summary>
		/// <value>The country.</value>
		public string Country
		{
			get { return _Country; }
			set { _Country = value; }
		}

		private string _IP = string.Empty;
		/// <summary>
		/// Gets or sets the IP address.
		/// </summary>
		/// <value>The IP.</value>
		public string IP
		{
			get { return _IP; }
			set { _IP = value; }
		}

		private ICommentable _Parent;

		/// <summary>
		/// 
		/// </summary>
		public ICommentable Parent
		{
			get { return _Parent; }
			set
			{
				_Parent = value;
				Title = Author + " on " + Parent.Title;
			}
		}

		private bool _IsApproved;
		/// <summary>
		/// Gets or sets the Comment approval status
		/// </summary>
		public bool IsApproved
		{
			get { return _IsApproved; }
			set { _IsApproved = value; }
		}

		#endregion

		#region IComparable<Comment> Members

		/// <summary>
		/// Compares the current object with another object of the same type.
		/// </summary>
		/// <param name="other">An object to compare with this object.</param>
		/// <returns>
		/// A 32-bit signed integer that indicates the relative order of the 
		/// objects being compared. The return value has the following meanings: 
		/// Value Meaning Less than zero This object is less than the other parameter.
		/// Zero This object is equal to other. Greater than zero This object is greater than other.
		/// </returns>
		public int CompareTo(Comment other)
		{
			return CompareOrderAndTitle(this.Order, this.DateCreated, this.Title, other.Order, other.DateCreated, other.Title);
		}

		#endregion

		#region Events


		/// <summary>
		/// Occurs just before a comment is approved by the comment moderator.
		/// </summary>
		public static event EventHandler<CancelEventArgs> Approving;
		/// <summary>
		/// Raises the event in a safe way
		/// </summary>
		internal static void OnApproving(Comment comment, CancelEventArgs e)
		{
			if (Approving != null)
			{
				Approving(comment, e);
			}
		}

		/// <summary>
		/// Occurs when the page is being attacked by robot spam.
		/// </summary>
		public static event EventHandler<EventArgs> SpamAttack;
		/// <summary>
		/// Raises the SpamAttack event in a safe way
		/// </summary>
		public static void OnSpamAttack()
		{
			if (SpamAttack != null)
			{
				SpamAttack(null, new EventArgs());
			}
		}

		/// <summary>
		/// Occurs after a comment is approved by the comment moderator.
		/// </summary>
		public static event EventHandler<EventArgs> Approved;
		/// <summary>
		/// Raises the event in a safe way
		/// </summary>
		internal static void OnApproved(Comment comment)
		{
			if (Approved != null)
			{
				Approved(comment, EventArgs.Empty);
			}
		}

		#endregion

		#region Base overrides

		/// <summary>
		/// Validates the item instance.
		/// </summary>
		/// <remarks>
		/// Each derived class should override this and ensure they call base.ValidationRules()
		/// to get a composite set of rules.
		///</remarks>
		protected override void ValidationRules()
		{
			AddRule("Content", "Content must be set", String.IsNullOrEmpty(Content));
			base.ValidationRules();
		}

		#endregion

		//TODO - comments on comments - while the data model supports it after mads changes this might break.

		/// <summary>
		/// Gets the relative link of the comment which is actually the parent item with a #id on the end.
		/// </summary>
		/// <value>The relative link.</value>
		protected override string RelativeLinkCore()
		{
			return Parent.RelativeLink + "#id_" + Id;
		}
		/// <summary>
		/// Gets the absolute link of the comment which is actually the parent item with a #id on the end.
		/// </summary>
		/// <returns></returns>
		protected override string AbsoluteLinkCore()
		{
			return Parent.AbsoluteLink + "id_" + Id;
		}

		/// <summary>
		/// 
		/// </summary>
		/// <returns></returns>
		protected override string RelativeLinkPrefix()
		{
			return string.Empty;
		}

		protected override string PermaLinkPrefix()
		{
			return "post";            //TODO - this is broken - work out use cases!
		}

		protected override void DataDelete()
		{
			throw new Exception("The method or operation is not implemented.");
		}

		protected override void DataInsert()
		{
			throw new Exception("The method or operation is not implemented.");
		}

		protected override Comment DataSelect(Guid id)
		{
			throw new Exception("The method or operation is not implemented.");
		}

		protected override void DataUpdate()
		{
			throw new Exception("The method or operation is not implemented.");
		}
	}
}
